#include <stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>



// 子线程(听筒)：接收来自对方的UDP数据
void * recv_msg(void* arg)        
{
    // 1、将自身设置为分离属性(此线程函数结束后，自动有人给它收尸)
    pthread_detach(pthread_self());     // pthread_self函数可以获取自己的线程id

    // 2、转换参数的类型
    int *p = (int*)arg;

    // 3、正常运行的线程功能(接收来自于对方发过来的信息)
    while (1)
    {
        char buf[1024] = {0};
        printf("正在等待对方发来数据:\n");
        ssize_t len = recvfrom(*p, buf, sizeof(buf), 0, NULL, NULL);
        printf("接收到的数据大小为：%ld, 内容为: %s\n", len, buf);

        if (strncmp(buf, "byebye", 6) == 0)
        {
           break;
        }
             
    }
}

// 主线程(发声孔): 发送信息给对方
int main(int argc, char const *argv[])
{
    // 1、创建UDP通信对象(a、买了一部手机)
    int  udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
    if (udp_socket < 0)
    {
        perror("创建UDP对象失败!\n");
        return -1;
    }
    
    // 使套接字sockfd关联的地址在套接字关闭后立即释放
    int on = 1;
    setsockopt(udp_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));  //开启端口复用功能 

    // 2、设置自己的地址和端口号，并绑定(b、填写自己的信息，并插卡)  --- 你想接收信息，就一定要设置
    // struct sockaddr *addr;                           // 旧地址结构体，已经废弃掉了
    struct sockaddr_in addr;                            // 创建一个服务器地址结构体
    addr.sin_family      = AF_INET;                     // 设置地址族为IPv4
    addr.sin_port        = htons(6666);                 // 设置端口号为8080
    addr.sin_addr.s_addr = INADDR_ANY;                  // 设置IP地址为本机器的所有地址

    int ret_b = bind(udp_socket, (struct sockaddr *)&addr, sizeof(addr));
    if (ret_b < 0)
    {
       perror("绑定失败!\n");
       return -2;
    }

    // 3、填写对方的信息
    // struct sockaddr *addr;                               // 旧地址结构体，已经废弃掉了
    struct sockaddr_in dest_addr;                           // 创建一个服务器地址结构体
    dest_addr.sin_family      = AF_INET;                    // 设置地址族为IPv4
    dest_addr.sin_port        = htons(8888);                // 设置端口号为6666
    dest_addr.sin_addr.s_addr = inet_addr("192.168.10.2");  // 设置IP地址为192.168.10.2


   // 4、子线程(听筒)：接收来自对方的UDP数据
    pthread_t recv_msg_ptid;
    pthread_create(&recv_msg_ptid, NULL, recv_msg, (void*)&udp_socket);

    
   // 5、主线程(发声孔): 发送UDP数据包给对方
    while (1)
    {
        char buf[1024] = {0};
        printf("请输入要对对方说的话:\n");
        scanf("%s", buf);

        ssize_t len = sendto(udp_socket, buf, strlen(buf), 0, (struct sockaddr *)&dest_addr, sizeof(addr));
        printf("发送的数据包的大小为：%ld字节\n", len);

        if (strncmp(buf, "byebye", 6) == 0)
        {
           break;
        }
    }
    

    // 4、结束通信
    close(udp_socket);
    

    return 0;
}
